//
//  XPBaseWebViewController.swift
//  PPKit
//
//  Created by xiaopin on 2019/8/16.
//  Copyright © 2019 scoresdata.net. All rights reserved.
//

import UIKit
import WebKit
import MJRefresh

/// js调用本地的方法枚举
enum NativeMethodsEnum:String {
    /// 返回
    case goback = "goback"
    /// 改变状态栏样式
    case changeStatusBarStyle = "changeStatusBarStyle"
    /// 设置浏览器标题
    case resetTitle = "setTitle"
    /// 是否显示导航栏
    case showNavBar = "showNavBar"
    /// 重置页面背景色
    case resetBGColor = "resetBGColor"
    /// 设置是否可以刷新,true 允许刷新
    case refreshState = "refreshState"
    /// 加载本地配置信息
    case loadNativeSetting = "loadNativeSetting"
    /// 执行登录
    case doLogin = "doLogin"
    /// api调用
    case apiCall = "apiCall"
    /// 获取本地图片
    case getImage = "getImage"
    /// 分享
    case share = "share"
    /// 获取定位信息
    case getLocation = "getLocation"
    /// 切换到指定Tabbar
    case switchTabItem = "switchTabItem"
    /// 打开相机
    case openCamera = "openCamera"
    /// 打开相册
    case openPhotoLibrary = "openPhotoLibrary"
    /// 打开视频相册
    case openVideoLibrary = "openVideoLibrary"
    /// 打开三方App或页面
    case openApp = "openApp"
    /// 打开页面
    case openPage = "openPage"
    /// 打开积分任务
    case openIntegralPage = "openIntegralPage"
    /// 打开积分任务
    case openIntegralTask = "openIntegralTask"
    /// 打开积分详情
    case openIntegralDetailPage = "openIntegralDetailPage"
    /// 打开个人主页
    case openPersonPage = "openPersonPage"
    /// 打开个人主页
    case toPersonPage = "toPersonPage"
    /// 打开文章详情
    case openArticleDetailPage = "openArticleDetailPage"
    /// 打开文章详情
    case openArticleDetail = "openArticleDetail"
    /// 打开帖子详情
    case openPostDetailPage = "openPostDetailPage"
    /// 打开帖子详情
    case openPostDetail = "openPostDetail"
    /// 打开方案详情
    case openPlanDetailPage = "openPlanDetailPage"
    /// 打开方案详情
    case openPlanDetail = "openPlanDetail"
    /// 打开比赛详情
    case openGameDetailPage = "openGameDetailPage"
    /// 打开比赛详情
    case openMatchDetail = "openMatchDetail"
    /// 打开新的Web页 
    case openH5DetailPage = "openH5DetailPage"
    /// 打开圈子
    case openMaotiCirclePage = "openMaotiCirclePage"
    /// 打开球迷圈
    case openFanceCirclePage = "openFanceCirclePage"
    /// 打开绑定手机
    case openBindPhonePage = "openBindPhonePage"
    /// 打开会员中心
    case openVipPage = "openVipPage"
    /// 打开我的钱包
    case openWalletPage = "openWalletPage"
}

enum WebViewRequestType {
    case webUrl
    case htmlString
    case htmlFile
}

/// H5网页
class XPBaseWebViewController: XPBaseViewController {
    
    //MARK: 公开属性
    var requestType:WebViewRequestType = .webUrl
    /// H5网络地址
    var webUrl:String?
    var htmlString:String?
    var localFilePath:String?
    //0.默认白色，1.蓝色主题色
    var navStyle:Int = 0
    /// 是否隐藏导航栏
    var navHidden:Bool = false
    var progressHidden:Bool = false
    
    //MARK: 私有属性
    private var statusBarStyle:String = "black"
    /// 当前主题样式
    private var themeMode:ThemeMode = .light
    /// 注册本地方法集合
    private var nativeMethods:[NativeMethodsEnum] = [.goback,.changeStatusBarStyle,.resetTitle,.showNavBar,.resetBGColor,.refreshState,.loadNativeSetting,.doLogin,.apiCall,.getImage,.share,.getLocation,.switchTabItem,.openCamera,.openPhotoLibrary,.openVideoLibrary,.openApp,.openPage,.openIntegralPage,.openIntegralTask,.openIntegralDetailPage,.openPersonPage,.toPersonPage,.openArticleDetail,.openArticleDetailPage,.openPostDetail,.openPostDetailPage,.openPlanDetail,.openPlanDetailPage,.openMatchDetail,.openGameDetailPage,.openH5DetailPage,.openMaotiCirclePage,.openFanceCirclePage,.openBindPhonePage,.openVipPage,.openWalletPage]
    /// js登录参数
    private var loginParams:[String:Any]?
    //MARK: 懒加载
    lazy var progressView:UIProgressView = {
        let view = UIProgressView(frame:pp_frame(0,0,pp_screen_width,3))
        return view
    }()
    
    /// webView对象
    lazy var webView: WKWebView = {
        let webv = WKWebView(frame: pp_frame(0,0,pp_screen_width,pp_screen_height), configuration: webConfiguration)
        webv.backgroundColor = .white
        webv.navigationDelegate = self
        webv.uiDelegate = self
        webv.isOpaque = false
        webv.setValue("maoti/\(pp_AppVersion)", forKey: "applicationNameForUserAgent")
        webv.allowsBackForwardNavigationGestures = true
        webv.scrollView.contentInsetAdjustmentBehavior = .never
        webv.scrollView.showsHorizontalScrollIndicator = false
        webv.scrollView.showsVerticalScrollIndicator = false
        webv.scrollView.mj_header = XPCustomHeader.init(refreshingTarget: self, refreshingAction: #selector(refreshPage))
        webv.addObserver(self, forKeyPath: "estimatedProgress", options: .new, context: nil)
        return webv
    }()
    
    /// webView配置信息
    lazy var webConfiguration: WKWebViewConfiguration = {
        let configuration = WKWebViewConfiguration.init()
        // 创建设置对象
        let preferences = WKPreferences.init()
        // 在iOS上默认为NO，表示是否允许不经过用户交互由javaScript自动打开窗口
        preferences.javaScriptCanOpenWindowsAutomatically = true
        // 最小字体大小 当将javaScriptEnabled属性设置为NO时，可以看到明显的效果
        preferences.minimumFontSize = 0
        // 偏好设置
        configuration.preferences = preferences
        // 原生方法注入
        configuration.userContentController = self.webUserContentController
        // 是使用h5的视频播放器在线播放, 还是使用原生播放器全屏播放
        configuration.allowsInlineMediaPlayback = true
        //设置是否允许画中画技术 在特定设备上有效
        configuration.allowsPictureInPictureMediaPlayback = true
        return configuration
    }()
    
    /// 供js调用的方法注册
    lazy var webUserContentController: WKUserContentController = {
        let userConetentController = WKUserContentController()
        
        let settingJS = """
        window.settings = {
            "Version":"\(pp_AppVersion)",
            "Platform":"iOS",
            "Platform-Version":"\(pp_DeviceSystemName) \(pp_DeviceSystemVersion)",
            "DeviceName":"\(pp_DeviceModelName)",
            "Screen-Size":"\(pp_screen_width.i)x\(pp_screen_height.i)",
            "Navbar-Height":\(pp_screen_navbar_height.i),
            "Statusbar-Height":\(pp_screen_statusbar_height.i)
        }
        """
        let userScript = WKUserScript.init(source: settingJS, injectionTime: .atDocumentStart, forMainFrameOnly: true)
        userConetentController.addUserScript(userScript)
        nativeMethods.forEach({ userConetentController.add(self, name: $0.rawValue)})
        return userConetentController
    }()
    
    //MARK: 默认基类方法
    override var preferredStatusBarStyle: UIStatusBarStyle{
        return statusBarStyle == "white" ? .lightContent : .default
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        initData()
        initNotification()
        initNavigationBar()
        initSubViews()
        loadData()
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        if navHidden {
            super.hideNavigationBar(animated)
        }else{
            super.showNavigationBar(animated)
        }
    }
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        
    }
    deinit{
        webUserContentController.removeAllUserScripts()
        webUserContentController.removeAllContentRuleLists()
        if #available(iOS 14.0, *) {
            webUserContentController.removeAllScriptMessageHandlers()
        } else {
            nativeMethods.forEach({ webUserContentController.removeScriptMessageHandler(forName: $0.rawValue)})
        }
        NotificationCenter.default.removeObserver(self)
        PPLog("成功移除WebView注入资源和注册通知")
    }
}

//MARK: #重写基类方法#
extension XPBaseWebViewController{
    override func initData() {
        super.initData()
        
        themeMode = XPApplication.shared.themeMode == ThemeMode.dark ? .dark : .light
    }
    
    override func initNavigationBar() {
        //self.title = "H5"
        if navStyle == 0 {
            super.initNavigationBar()
        }else{
            super.initNavigationBar2()
        }
    }
    
    override func initSubViews() {
        super.initSubViews()
        
        webView.beAddInto(view).snp.remakeConstraints { m in
            m.top.left.bottom.right.equalToSuperview()
        }
        view.addSubview(progressView)
        
        addSwipeRightGesture()
    }
    
    override func loadData() {
        let username = currentUser()?.nickName ?? ""
        let token = currentUser()?.token ?? ""
  
        switch requestType {
        case .webUrl:
            guard let newUrl = webUrl else{return}
            if let url = URL(string: newUrl) {
                PPLog("请求地址：\(url)")
                let request = URLRequest.init(url: url, cachePolicy: .reloadRevalidatingCacheData, timeoutInterval: 15)
                webView.load(request)
            }else{
                showAlert("请求地址错误")
            }
        case .htmlFile:
            let url = URL(fileURLWithPath: localFilePath!)
            webView.loadFileURL(url, allowingReadAccessTo: url)
        case .htmlString:
            webView.loadHTMLString(htmlString ?? "", baseURL: nil)
        }
    }
    
    override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
        super.traitCollectionDidChange(previousTraitCollection)
        if #available(iOS 13.0, *){
            if traitCollection.hasDifferentColorAppearance(comparedTo: previousTraitCollection) && XPApplication.shared.themeMode == .default{
                themeMode = traitCollection.userInterfaceStyle == .dark ? .dark : .light
                webView.evaluateJavaScript("javascript:window.__refreshThemeStyle('\(themeMode == .dark ? "dark" : "light")')") { (res, error) in
                    PPLog("切换主题完成")
                }
            }
        }
    }
}

//MARK: #自定义方法#
extension XPBaseWebViewController{
    func refreshPage(){
        webView.reload()
    }
}

//MARK: #事件通知#
extension XPBaseWebViewController{
    override func loginStateChanged(_ notify: Notification) {
        guard let params = loginParams else {
            loadData()
            return
        }
        if let isReload = params["reload"] as? Bool, isReload == true {
            loadData()
        }else{
            if let loginCallBack = loginParams?["callBackMethod"] as? String {
                webView.evaluateJavaScript("javascript:\(loginCallBack)({login:\(isLogined()),token:'\(currentToken())',userId:\(currentUserId())})") { (res, error) in
                    PPLog("登录回调成功")
                }
                loginParams = nil
            }
        }
    }
}

//MARK: #WK本地注册的方法#
extension XPBaseWebViewController{
    /// 返回
    override func backAction() {
        //根据推出来源进行操作
        switch pushSource {
        case .fromMain:
            self.navigationController?.popToRootViewController(animated: true)
        case .fromWelcome:
            NotificationCenter.default.post(name: .mtBackToWelcome, object: nil)
        default:
            self.navigationController?.popViewController(animated: true)
        }
    }
    
    /// 改变状态栏样式
    /// - Parameter params: black黑色，white白色
    func changeStatusBarStyle(_ params:Any){
        guard let style = params as? String else { return }
        statusBarStyle = style
        setNeedsStatusBarAppearanceUpdate()
    }
    
    /// 重置标题
    /// - Parameter params: <#params description#>
    func resetTitle(_ params:Any){
        guard let value = params as? String else { return }
        self.title = value
        initNavigationBar()
    }
    
    /// 是否显示导航栏
    /// - Parameter params: <#params description#>
    func showNavBar(_ params:Any){
        guard let value = params as? Bool else { return }
        navHidden = !value
        navigationController?.setNavigationBarHidden(navHidden, animated: true)
    }
    
    /// 重置页面背景色
    /// - Parameter params: 16进制颜色
    func resetBGColor(_ params:Any){
        guard let value = params as? String else { return }
        view.backgroundColor = UIColor.hexColor(value)
        webView.backgroundColor = UIColor.hexColor(value)
    }
    
    /// 设置是否允许下拉刷新
    /// - Parameter params: 16进制颜色
    func refreshState(_ params:Any){
        guard let value = params as? Bool else { return }
        if value == false {
            webView.scrollView.mj_header = nil
        }
    }
    
    /// 获取本地配置信息
    /// - Parameter params: js代码
    func loadNativeSetting(_ params:Any){
        guard let dict = params as? [String:Any] else { return }
        guard let callback = dict["callBackMethod"] as? String else{ return }
        
        let settings:[String:Any] = [
            "Version":"\(pp_AppVersion)",
            "Platform":"iOS",
            "Platform-Version":"\(pp_DeviceSystemName) \(pp_DeviceSystemVersion)",
            "DeviceName":"\(pp_DeviceModelName)",
            "Screen-Size":"\(pp_screen_width.i)x\(pp_screen_height.i)",
            "Navbar-Height":pp_screen_navbar_height,
            "Statusbar-Height":pp_screen_statusbar_height,
            "IsLogined":isLogined(),
            "UserId":currentUserId(),
            "Token":currentUser()?.token ?? "",
            "ThemeStyle":themeMode == .dark ? 1 : 0
        ]
        
        let jsonStr = pp_json_toString(settings) ?? ""
        webView.evaluateJavaScript("javascript:\(callback)(\(jsonStr))", completionHandler: { (res, error) in
            PPLog("成功注入本地配置信息")
        })
    }

    /// 执行登录
    /// - Parameter params: <#params description#>
    func doLogin(_ params:Any){
        loginParams = params as? [String:Any]
        if !isLogined(){
            toLoginPageByModal()
        }else{
            if let loginCallBack = loginParams?["callBackMethod"] as? String {
                webView.evaluateJavaScript("javascript:\(loginCallBack)({login:\(isLogined()),token:'\(currentToken())',userId:\(currentUserId())})") { (res, error) in
                    PPLog("登录回调成功")
                }
            }
        }
    }
    
    /// js调用本地请求API
    /// - Parameter params: {url:"请求Api全路径",method:"请求方式",params:{请求json对象},resultType:"结果集类型Int,Bool,String,Array,Object",callBackMethod:"H5回调方法(结果统一转成字符串)"}
    func apiCall(_ params:Any){
        guard let dict = params as? [String:Any] else{
            showAlert("失败的请求")
            return
        }
        guard let url = dict["url"] as? String else{return}
        guard let method = dict["method"] as? String else{return}
        guard let params = dict["params"] as? [String:Any] else{return}
        
        XPNetworkApi.shared.h5request(url, method: method == "get" ? .get : .post, params) { [weak self] (msg, count, res) in
            if let callback = dict["callBackMethod"] as? String {
                let jsCode = "javascript:\(callback)('\(res as? String ?? "")')"
                self?.webView.evaluateJavaScript(jsCode) { (res, error) in
                    PPLog("回调\(jsCode)")
                }
            }
        } failed: { (msg, code) in
            showAlert(msg)
        }
    }
    
    /// 获取本地图片
    /// - Parameter params: {imgId:"img标签ID",imgUrl:"图片网络地址"}
    func getImage(_ params:Any){
        //1.判断URL的合法性
        guard let dict = params as? [String:Any] else { return }
        let imgId = dict["imgId"] as? String ?? ""
        let url = dict["imgUrl"] as? String ?? ""
        guard let imageURL = URL(string: url) else { return}
        //2.构建存储路径
        let ext = imageURL.pathExtension
        if ["png","jpg","jpeg","gif","avif"].contains(ext) == false {
            showAlert("非图片格式请求")
            return
        }
        let imageStorePath = XPSandbox.shared.buildCachesPath(.images, "\(url.MD5).\(ext)")
        
        //3.下载网络图片到本地
        XPNetworkApi.shared.download(url: url, destination: imageStorePath) { (progress) in
            PPLog("\(url) 下载进度:\(progress)")
        } finished: { [weak self] (msg, nil, res) in
            PPLog("下载完成:\(url)")
            //4.回调网络URL和本地URL
            if let callback = dict["callBackMethod"] as? String {
                let filePath = URL(fileURLWithPath: imageStorePath).absoluteString
                let jsCode = "javascript:\(callback)({imgId:'\(imgId)',imageUrl:'\(url)',localImagePath:'\(filePath)'})"
                self?.webView.evaluateJavaScript(jsCode) { (res, error) in
                    PPLog("回调\(jsCode)")
                }
            }
        } failed: { (msg, code) in
            PPLog("获取本地图片失败")
        }
    }
    
    /// 获取本地文件
    /// - Parameter params: {objId:"html标签ID",fileUrl:"文件网络地址"}
    func getFile(_ params:Any){
        //1.判断URL的合法性
        guard let dict = params as? [String:Any] else { return }
        let objId = dict["objId"] as? String ?? ""
        let url = dict["fileUrl"] as? String ?? ""
        guard let fileURL = URL(string: url) else { return }
        //2.构建存储路径
        let ext = fileURL.pathExtension
        var fileStorePath = ""
        if ["png","jpg","jpeg","gif","avif"].contains(ext){
            fileStorePath = XPSandbox.shared.buildCachesPath(.images, "\(url.MD5).\(ext)")
        }else{
            fileStorePath = XPSandbox.shared.buildDocsPath(.files, "\(url.MD5).\(ext)")
        }
        
        //3.下载网络图片到本地
        XPNetworkApi.shared.download(url: url, destination: fileStorePath) { (progress) in
            PPLog("\(url) 下载进度:\(progress)")
        } finished: { [weak self] (msg, nil, res) in
            PPLog("下载完成:\(url)")
            //4.回调网络URL和本地URL
            if let callback = dict["callBackMethod"] as? String {
                let filePath = URL(fileURLWithPath: fileStorePath).absoluteString
                let jsCode = "javascript:\(callback)({objId:'\(objId)',fileUrl:'\(url)',localFilePath:'\(filePath)'})"
                self?.webView.evaluateJavaScript(jsCode) { (res, error) in
                    PPLog("回调\(jsCode)")
                }
            }
        } failed: { (msg, code) in
            PPLog("获取本地图片失败")
        }
    }

    /// 分享
    /// - Parameter params: 分享传递过来的参数字典:标题、描述、图片链接数组[]、网页链接
    func share(_ params:Any){
        /*
        guard let dict = params as? [String:Any] else{return}
        guard let shareTitle = dict["title"] as? String else{return}
        let shareSummary = dict["summary"] as? String ?? ""
        let shareImageUrls = dict["images"] as? [String] ?? [kShareDefaultPic]
        guard let shareLinkUrl = dict["linkUrl"] as? String else{return}
        
        var platforms = [SharePlatform]()
        if let platform = dict["platform"] as? String {
            platform.components(separatedBy: ",").forEach { (value) in
                if let enumValue = SharePlatform(rawValue: value) {
                    platforms.append(enumValue)
                }
            }
        }
        if platforms.count == 0 {
            platforms = [.weibo,.weixin,.pyq,.qqzone]
        }
    
        let shareObj = XPShareView(frame: pp_frame(0, 0, pp_screen_width, pp_screen_height), platforms: platforms)
        shareObj.share(shareTitle, shareSummary, shareImageUrls, shareLinkUrl)
        shareObj.eventClosure = { [weak self] (eventType) in
            switch eventType {
            case .success:
                PPLog("分享成功")
                if let callback = dict["callBackMethod"] as? String {
                    let jsCode = "javascript:\(callback)(true)"
                    self?.webView.evaluateJavaScript(jsCode) { (res, error) in
                        PPLog("回调\(jsCode)")
                    }
                }
            case .failed:
                if let callback = dict["callBackMethod"] as? String {
                    let jsCode = "javascript:\(callback)(false)"
                    self?.webView.evaluateJavaScript(jsCode) { (res, error) in
                        PPLog("回调\(jsCode)")
                    }
                }
            case .cancel:
                if let callback = dict["callBackMethod"] as? String {
                    let jsCode = "javascript:\(callback)(false)"
                    self?.webView.evaluateJavaScript(jsCode) { (res, error) in
                        PPLog("回调\(jsCode)")
                    }
                }
            default:
                break
            }
        }*/
    }
    
    /// 获取定位信息
    /// - Parameter params: js代码
    func getLocation(_ params:Any){
        guard let dict = params as? [String:Any] else { return }
        XPLocation.shared.startLocation().detailClosure = { [weak self] (location) in
            if let callback = dict["callBackMethod"] as? String {
                self?.webView.evaluateJavaScript("javascript:\(callback)(\(location.toJSONString() ?? "")", completionHandler: { (res, error) in
                    PPLog("获取定位信息成功并返回数据")
                })
            }
        }
    }
    
    /// 切换到指定TabBar（如果有变动，通知前端）
    func switchTabItem(_ params:Any){
        guard let dict = params as? [String:Any] else{return}
        //tabKey: [(1,"home"),(2,"bifen"),(3,"expert"),(4,"find"),(5,"me"),(6,"data"),(7,"circle"),(8,"web"),(9,"fanscircle")]
        guard let tabKey = dict["tabKey"] as? String else{return}
    
        if let tabBarVC = pp_keyWindow()?.rootViewController as? XPTabBarController {
            var index = 0
            for (i,item) in tabBarVC.tabValues.enumerated() {
                if item.key == tabKey {
                    index = i
                    break
                }
            }
            tabBarVC.selectedIndex = index
        }
    }
    
    /// 打开相机
    /// - Parameter params: js代码
    func openCamera(_ params:Any){
        guard let value = params as? String else { return }
        
    }
    
    /// 打开相册
    /// - Parameter params: js代码
    func openPhotoLibrary(_ params:Any){
        guard let value = params as? String else { return }
        
    }
    
    /// 打开视频相册
    /// - Parameter params: js代码
    func openVideoLibrary(_ params:Any){
        guard let value = params as? String else { return }
        
    }
    
    /// 打开三方App或页面
    /// - Parameter params: params description
    func openApp(_ params:Any){
        guard let value = params as? String else { return }
        guard let url = URL(string: value) else {return}
        if UIApplication.shared.canOpenURL(url){
            UIApplication.shared.open(url, options: [:], completionHandler: nil)
        }
    }
    
    /// 打开页面（如果有变动，通知前端）
    /// - Parameter params: params description
    func openPage(_ params:Any){
        guard let dict = params as? [String:Any] else { return }
        guard let classEncryptStr = dict["className"] as? String else{return}
        /*
         {"className":"密文",params:{"userId":123}}
         打开H5页：XPBaseWebViewController      AUEAYEfQcikxwsfqHICkbnl/1A5AXjCI
         个人主页：MTUserDetailController       1HQLikS7YOtk8zuhEBKhbv4vLIVnX0g0
         文章详情：MTNewsDetailViewController    5D/YNex1Gt6/BXj6nB1A+2SGOTo2/CT3clZW9OhldAY=
         帖子详情：MTCirclePostDetailViewController  fXtFCUiplGzxCIat8rqD12VfzhEcq0jKxCBaHOWNp9ydSeMLPEPH3g==
         方案详情：MTExpertPlanDetailController  OiF+hZQ2s0upnBNIlT/rvndCs1zx7vw+yiN2wabje7s=
         比赛详情：MTMatchDetailViewController   r7Wx+/+vgW4Uc8YEje0gMgtuEqyDlY8pttBGYVTIhrQ=
         积分任务：MyIntegralNewVC   Ktg2N1OQEEwz6/XwvuCuMw==
         积分明细：MyIntegralDetailVC    Ktg2N1OQEEwsrrTLfH+gmvfcNXmRa0f1
         圈子：MTCircleHomeViewController     fXtFCUiplGwO5qeYBi109mSGOTo2/CT3clZW9OhldAY=
         球迷圈：MTFindFansCircleMainController +iE95xHMCI/x6IuuSYWTjwjkTvuNd1JJ/i8shWdfSDQ=
         绑定手机：MTMyIphoneBindingSafeVC   BZLu5X8Scj/0Z0foWAPOkSgIxOynmW3+
         会员中心：MTVipCenterViewController     cDwE2AqxF+VrLh30anS7n292d356gwSBT4USUEDN51Y=
         我的钱包：MTMyWalletViewController      tF6sVBEB/Bw40UGuWSby2cQgWhzljafcnUnjCzxDx94=
         */
        let className = XPEncryptUtil.BlowfishDecrypt(classEncryptStr)
        switch className {
        case "MyIntegralDetailVC":
            if !isLogined() { toLoginPageByModal() }
        default:
            break
        }
        if let vc = pp_init_vc(className, dict["params"] as? [String:Any]){
            push(vc)
        }
    }
    
    /// 跳转到个人主页
    /// - Parameter params: 用户ID
    func openPersonPage(_ params:Any) {
        guard let userId = params as? Int, userId > 0 else {return}
//        let vc = MTUserDetailController()
//        vc.userId = userId
//        push(vc)
    }
    
    /// 打开比赛详情
    /// - Parameter params: 赛事ID
    func openGameDetailPage(_ params:Any) {
        guard let dict = params as? [String:Any] else{return}
        guard let id = dict["id"] as? Int,id > 0 else{return}
        guard let tabKey = dict["tabKey"] as? String else{return}
        
//        let vc = MTMatchDetailViewController()
//        vc.matchId = id
//        vc.tabKey = tabKey
//        push(vc)
    }
    
    /// 打开H5新页面
    /// - Parameter params: H5地址
    func openH5DetailPage(_ params:Any) {
        guard let webUrl = params as? String else { return }
//        let vc = MTWebViewController()
//        vc.webUrl = webUrl
//        vc.navHidden = true
//        push(vc)
    }
}


//MARK: #委托代理#
extension XPBaseWebViewController:WKUIDelegate,WKNavigationDelegate,WKScriptMessageHandler{
    //MARK: WKNavigationDelegate
    //决定导航的动作，通常用于处理跨域的链接能否导航。WebKit对跨域进行了安全检查限制，不允许跨域，因此我们要对不能跨域的链接单独处理。但是，对于Safari是允许跨域的，不用这么处理。
    //这个是决定是否Reques，在发送请求之前，决定是否跳转
    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        PPLog("navigationAction")
        /*
         在这个方法你可以做的操作有：
         1.拦截地址，做特殊处理
         2.拦截tel电话
         ...
         示例：
         // 打开appstore
         if ([url.absoluteString containsString:@"ituns.apple.com"]) {
         if ([app canOpenURL:url]) {
         [app openURL:url];
         decisionHandler(.cancel);//每次做特殊处理后取消请求
         return;
         }
         }
         */
        guard let url = webView.url else {
            decisionHandler(.cancel)
            return
        }
        //打开AppStore下载
        if url.absoluteString.contains("apps.apple.com") || url.absoluteString.contains("ituns.apple.com") {
            if UIApplication.shared.canOpenURL(url) {
                UIApplication.shared.open(url, options: [:], completionHandler: nil)
                decisionHandler(.cancel)
                return
            }
        }
        //拨打电话
        if url.absoluteString.hasPrefix("tel"){
            if UIApplication.shared.canOpenURL(url){
                UIApplication.shared.open(url, options: [:], completionHandler: nil)
                decisionHandler(.cancel)
                return
            }
        }
        decisionHandler(.allow)
    }
    
    // 决定是否接收响应
    // 这个是决定是否接收response
    // 要获取response，通过WKNavigationResponse对象获取
    func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
        PPLog("webView->navigationResponse")
        decisionHandler(.allow)
    }
    
    // 当main frame的导航开始请求时，会调用此方法，开始加载时调用
    func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
        PPLog("webView->didStartProvisionalNavigation")
        /*
         在这里可以做加载动画的开始
         */
    }
    
    // 当main frame接收到服务重定向时，会回调此方法，接收到服务器跳转请求之后调用
    func webView(_ webView: WKWebView, didReceiveServerRedirectForProvisionalNavigation navigation: WKNavigation!) {
        PPLog("webView->didReceiveServerRedirectForProvisionalNavigation")
    }
    
    // 当main frame开始加载数据失败时，会回调，页面加载失败时调用
    func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
        PPLog("webView->didFailProvisionalNavigation:\(error.localizedDescription)")
    }
    
    // 当main frame的web内容开始到达时，会回调，当内容开始返回时调用
    func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
        PPLog("webView->didCommit navigation")
    }
    
    // 当main frame导航完成时，会回调，页面加载完成之后调用
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        PPLog("webView->didFinish navigation \(webView.scrollView.contentSize)")
        
        webView.scrollView.mj_header?.endRefreshing()
        //userAgent: Mozilla/5.0 (iPhone; CPU iPhone OS 13_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148)
        
    }

    // 当main frame最后下载数据失败时，会回调
    func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
        PPLog("webView->didFail navigation")
        
    }
    
    // 这与用于授权验证的API，与AFN、的授权验证API是一样的
    //    func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
    //        PPLog("webView->didReceive challenge")
    //    }
    
    // 当web content处理完成时，会回调
    func webViewWebContentProcessDidTerminate(_ webView: WKWebView) {
        PPLog("webView->webViewWebContentProcessDidTerminate")
    }
    
    //MARK: WKUIDelegate
    //    func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
    //        return webView
    //    }
    
    
    //js中弹出alert
    func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) {
        //showAlert(message)
        present(UIAlertController.init(title: "提示", message: message, preferredStyle: .alert), animated: true)
        completionHandler()
    }
    
    //js中弹出confirm
    //    func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (Bool) -> Void) {
    //
    //    }
    
    //弹出输入框
    //    func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt prompt: String, defaultText: String?, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (String?) -> Void) {
    //
    //    }
    
    //自定义预览页面需要用到
    //    func webView(_ webView: WKWebView, shouldPreviewElement elementInfo: WKPreviewElementInfo) -> Bool {
    //
    //        return true
    //    }
    
    //    func webView(_ webView: WKWebView, previewingViewControllerForElement elementInfo: WKPreviewElementInfo, defaultActions previewActions: [WKPreviewActionItem]) -> UIViewController? {
    //        return nil
    //    }
    
    //    func webView(_ webView: WKWebView, commitPreviewingViewController previewingViewController: UIViewController) {
    //
    //    }
    
    func webViewDidClose(_ webView: WKWebView) {
        
    }
    //MARK: WKScriptMessageHandler
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        /*
         JS调用iOS方法：
         function shareClick(){
         3种传值方式
         window.webkit.messageHandlers.share.postMessage({platform:'',title:'测试标题',conent:'测试分享内容',imageUrl:'',linkUrl:''});
         window.webkit.messageHandlers.share.postMessage(1);
         window.webkit.messageHandlers.share.postMessage("字符串");
         }
         
         iOS调用js方法：
         [self.webView evaluateJavaScript:@"tycom.native.getTokenCallback(\"\")" completionHandler:^(id _Nullable item, NSError * _Nullable error) {
            NSLog(@"调用js完成");
         }];
         */
        PPLog("JS 调用了 \(message.name) 方法，传回参数 \(message.body)");
        //通用
        switch NativeMethodsEnum(rawValue: message.name) {
        case .goback:
            backAction()
        case .changeStatusBarStyle:
            changeStatusBarStyle(message.body)
        case .resetTitle:
            resetTitle(message.body)
        case .showNavBar:
            showNavBar(message.body)
        case .resetBGColor:
            resetBGColor(message.body)
        case .refreshState:
            refreshState(message.body)
        case .loadNativeSetting:
            loadNativeSetting(message.body)
        case .doLogin:
            doLogin(message.body)
        case .apiCall:
            apiCall(message.body)
        case .getImage:
            getImage(message.body)
        case .share:
            share(message.body)
        case .getLocation:
            getLocation(message.body)
        case .switchTabItem:
            switchTabItem(message.body)
        case .openCamera:
            openCamera(message.body)
        case .openPhotoLibrary:
            openPhotoLibrary(message.body)
        case .openVideoLibrary:
            openVideoLibrary(message.body)
        case .openApp:
            openApp(message.body)
        case .openPage:
            openPage(message.body)
        case .openIntegralPage,.openIntegralTask:
            openPage(["className":"Ktg2N1OQEEwz6/XwvuCuMw=="])
        case .openIntegralDetailPage:
            openPage(["className":"Ktg2N1OQEEwsrrTLfH+gmvfcNXmRa0f1"])
        case .openPersonPage,.toPersonPage:
            openPersonPage(message.body)
        case .openMatchDetail,.openGameDetailPage:
            openGameDetailPage(message.body)
        case .openH5DetailPage:
            openH5DetailPage(message.body)
        case .openMaotiCirclePage:
            openPage(["className":"fXtFCUiplGwO5qeYBi109mSGOTo2/CT3clZW9OhldAY="])
        case .openFanceCirclePage:
            openPage(["className":"+iE95xHMCI/x6IuuSYWTjwjkTvuNd1JJ/i8shWdfSDQ="])
        case .openBindPhonePage:
            openPage(["className":"BZLu5X8Scj/0Z0foWAPOkSgIxOynmW3+"])
        case .openVipPage:
            openPage(["className":"cDwE2AqxF+VrLh30anS7n292d356gwSBT4USUEDN51Y="])
        case .openWalletPage:
            openPage(["className":"tF6sVBEB/Bw40UGuWSby2cQgWhzljafcnUnjCzxDx94="])
        default:
            break
        }
    }
    
    //MARK: 加载进度KVO
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        if keyPath == "estimatedProgress" {
            if progressHidden == true {
                progressView.isHidden = true
                return
            }
            self.progressView.progress = Float(self.webView.estimatedProgress)
            if self.progressView.progress == 1.0 {
                self.progressView.isHidden = true
                self.progressView.progress = 0
            }else{
                self.progressView.isHidden = false
            }
        }
    }
}

